﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;
using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

namespace Client
{
    public class BaseRepository<T>
    {
        public string Login    { get; set; }
        public string Password { get; set; }

        public BaseRepository()
        {
            Login    = String.Empty;
            Password = String.Empty;
        }

        public BaseRepository(string login, string password)
        {
            Login    = login;
            Password = password;
        }

        public IEnumerable<T> ParseJson(string jsonArray)
        {
            try
            {
                List<T> resultList                    = new List<T>();
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));

                jsonArray = jsonArray.Trim('[', ']').Replace("},{", "}" + Defaults.DEFAULT_DELIMETER + "{");

                MemoryStream ms;
                foreach (string obj in jsonArray.Split(';'))
                {
                    ms = new MemoryStream(Encoding.Unicode.GetBytes(obj));

                    resultList.Add((T)serializer.ReadObject(ms));

                    ms.Close();
                }

                return resultList.AsEnumerable<T>();
            }
            catch { }

            return null;
        }
    }

    public class PositionRepository : BaseRepository<Position>, IPositionRepository
    {
        private const string GET_REQ     = Defaults.SERVER + @"position/?login=#login#&password=#password#";
        private const string ADD_REQ     = Defaults.SERVER + @"m/edit_position/?login=#login#&password=#password#&name=#name#&salary=#salary#&action=add";
        private const string GET_ALL_REQ = Defaults.SERVER + @"m/positions/?login=#login#&password=#password#";

        public PositionRepository() : base()
        {
        }

        public PositionRepository(string login, string password) : base(login, password)
        {
        }

        public Position GetData()
        {
            HttpWebResponse response = Client.GetResponse(GET_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                StreamReader responseReader = new StreamReader(response.GetResponseStream());
                string       jsonResult     = responseReader.ReadToEnd();

                response.Close();
                return ParseJson(jsonResult).First();
            }
            return null;
        }

        public bool AddPosition(Position position)
        {
            if (position != null)
            {
                HttpWebResponse response = Client.GetResponse(ADD_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password).Replace(@"#salary#", position.Salary.ToString()).Replace(@"#name#", position.Name),
                                                              "POST",
                                                              Defaults.DEFAULT_CONTENTTYPE,
                                                              null);

                if (response != null)
                {
                    response.Close();
                    return true;
                }
            }
            return false;
        }

        public bool EditPosition(Position oldPosition, Position newPosition)
        {
            // TODO:
            
            return false;
        }

        public bool DeletePosition(Position position)
        {
            // TODO:

            return false;
        }

        public IEnumerable<Position> GetAll()
        {
            HttpWebResponse response = Client.GetResponse(GET_ALL_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                StreamReader responseReader = new StreamReader(response.GetResponseStream());
                string       jsonResult     = responseReader.ReadToEnd();

                response.Close();
                return ParseJson(jsonResult);
            }
            return null;
        }
    }

    public class BankAccountRepository : BaseRepository<BankAccount>, IBankAccountRepository
    { 
        public BankAccountRepository() : base()
        {
        }

        public BankAccountRepository(string login, string password) : base(login, password)
        {
        }

        public BankAccount GetData()
        {
            // TODO:

            return null;
        }

        public bool AddBankAccount(BankAccount bankAccount)
        {
            // TODO:

            return false;
        }

        public bool EditBankAccount(BankAccount oldBankAccount, BankAccount newBankAccount)
        {
            // TODO:

            return false;
        }

        public bool DeleteBankAccount(BankAccount bankAccount)
        {
            // TODO:

            return false;
        }

        public IEnumerable<Task> GetAll()
        {
            // TODO:

            return null;
        }
    }

    public class PaymentRepository : BaseRepository<Payment>, IPaymentRepository
    {
        private const string GET_REQ = Defaults.SERVER + @"m/payments/?login=#login#&password=#password#&e_id=#e_id#";
        private const string ADD_REQ = Defaults.SERVER + @"m/payment/?login=#login#&password=#password#&e_id=#e_id#&amount=#amount#";

        public PaymentRepository(string login, string password) : base(login, password)
        {
        }

        public PaymentRepository() : base()
        {
        }

        public IEnumerable<Payment> GetData(Employee employee)
        {
            HttpWebResponse response = Client.GetResponse(GET_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password).Replace(@"#e_id#", employee.Id.ToString()),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                StreamReader responseReader = new StreamReader(response.GetResponseStream());
                string       jsonResult     = responseReader.ReadToEnd();

                response.Close();
                return ParseJson(jsonResult);
            }
            return null;
        }

        public bool AddPayment(Employee employee, int sum)
        {
            HttpWebResponse response = Client.GetResponse(ADD_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password).Replace(@"#e_id#", employee.Id.ToString()).Replace(@"#amount#", sum.ToString()),
                                                              "POST",
                                                              Defaults.DEFAULT_CONTENTTYPE,
                                                              null);

            if (response != null)
            {
                response.Close();
                return true;
            }

            return false;
        }

        public bool EditPayment(Payment oldPayment, Payment newPayment)
        {
            // TODO:

            return false;
        }

        public bool DeletePayment(Payment payment)
        {
            // TODO:

            return false;
        }

        public IEnumerable<Payment> GetAll()
        {
            // TODO:

            return null;
        }
    }

    public class TaskRepository : BaseRepository<Task>, ITaskRepository
    {
        private const string GET_REQ     = Defaults.SERVER + @"tasks/?login=#login#&password=#password#";
        private const string ADD_REQ     = Defaults.SERVER + @"m/edit_task/?login=#login#&password=#password#&name=#name#&e_id=#e_id#&estimation=#estimation#&payment=#payment#&penalty=#penalty#&action=add";
        private const string FINISH_REQ  = Defaults.SERVER + @"finish_task/?login=#login#&password=#password#&id=#id#";
        private const string GET_ALL_REQ = Defaults.SERVER + @"m/tasks/?login=#login#&password=#password#";
        
        public TaskRepository() : base()
        {
        }

        public TaskRepository(string login, string password) : base(login, password)
        {
        }

        public IEnumerable<Task> GetData()
        {
            HttpWebResponse response = Client.GetResponse(GET_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                StreamReader responseReader = new StreamReader(response.GetResponseStream());
                string       jsonResult     = responseReader.ReadToEnd();

                response.Close();
                return ParseJson(jsonResult);
            }
            return null;
        }

        public bool AddTask(Task task)
        {
            HttpWebResponse response = Client.GetResponse(ADD_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password).Replace(@"#name#", task.Title).Replace(@"#e_id#", task.EmployeeId.ToString()).Replace(@"#estimation#", task.EstimationTime).Replace(@"#payment#", task.Cost.ToString()).Replace(@"#penalty#"
                , task.Penalty.ToString()),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                response.Close();
                
                return true;
            }
            return false;
        }

        public bool EditTask(Task oldTask, Task newTask)
        {
            // TODO:

            return false;
        }

        public bool DeleteTask(Task task)
        {
            // TODO:

            return false;
        }

        public IEnumerable<Task> GetAll()
        {
            HttpWebResponse response = Client.GetResponse(GET_ALL_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                StreamReader responseReader = new StreamReader(response.GetResponseStream());
                string       jsonResult     = responseReader.ReadToEnd();

                response.Close();
                return ParseJson(jsonResult);
            }
            return null;
        }

        public bool FinishTask(Task task)
        {
            HttpWebResponse response = Client.GetResponse(FINISH_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password).Replace("#id#", task.Id.ToString()),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                response.Close();
                return true;
            }
            return false;
        }
    }

    public class TimeTableRepository : BaseRepository<TimeTable>, ITimeTableRepository
    {
        private const string LOGIN_REQ   = Defaults.SERVER + @"login/?login=#login#&password=#password#";
        private const string LOGOUT_REQ  = Defaults.SERVER + @"logout/?login=#login#&password=#password#";
        private const string GET_REQ     = Defaults.SERVER + @"log/?login=#login#&password=#password#";
        private const string GET_ALL_REQ = Defaults.SERVER + @"m/logs/?login=#login#&password=#password#";

        public TimeTableRepository() : base()
        {
        }
        
        public TimeTableRepository(string login, string password) : base(login, password)
        {
        }

        public IEnumerable<TimeTable> GetData()
        {
            HttpWebResponse response = Client.GetResponse(GET_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                StreamReader responseReader = new StreamReader(response.GetResponseStream());
                string       jsonResult     = responseReader.ReadToEnd();

                response.Close();
                return ParseJson(jsonResult);
            }
            return null;
        }

        public bool LogIn()
        {
            HttpWebResponse response = Client.GetResponse(LOGIN_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                response.Close();
                return true;
            }
            return false;
        }

        public bool LogOut()
        {
            HttpWebResponse response = Client.GetResponse(LOGOUT_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                response.Close();
                return true;
            }
            return false;
        }

        public IEnumerable<TimeTable> GetAll()
        {
            HttpWebResponse response = Client.GetResponse(GET_ALL_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                StreamReader responseReader = new StreamReader(response.GetResponseStream());
                string       jsonResult     = responseReader.ReadToEnd();

                response.Close();
                return ParseJson(jsonResult);
            }
            return null;
        }
    }

    public class EmployeeRepository : BaseRepository<Employee>, IEmployeeRepository
    {
        private const string GET_REQ     = Defaults.SERVER + @"employee_data/?login=#login#&password=#password#";
        private const string ADD_REQ     = Defaults.SERVER + @"m/edit_employee/?login=#login#&password=#password#&name=#name#&bank_account=#bankAccountId#&position=#positionId#&role=#role#&e_login=#e_login#&e_password=#e_password#&action=add";
        private const string EDIT_REQ    = Defaults.SERVER + @"m/edit_employee/?login=#login#&password=#password#&name=#name#&bank_account=#bankAccountId#&position=#positionId#&role=#role#&e_login=#e_login#&e_password=#e_password#&id=#id#&action=edit";
        private const string DEL_REQ     = Defaults.SERVER + @"m/edit_employee/?login=#login#&password=#password#&id=#id#&action=delete";
        private const string GET_ALL_REQ = Defaults.SERVER + @"m/employee_data/?login=#login#&password=#password#";

        public EmployeeRepository()  : base()
        {
        }

        public EmployeeRepository(string login, string password) : base(login, password)
        {
        }

        public Employee GetData()
        {
            HttpWebResponse response = Client.GetResponse(GET_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                StreamReader responseReader = new StreamReader(response.GetResponseStream());
                string       jsonResult     = responseReader.ReadToEnd();

                response.Close();
                return ParseJson(jsonResult).First();
            }
            return null;
        }

        public bool AddEmployee(Employee employee)
        {
            HttpWebResponse response = Client.GetResponse(ADD_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password).Replace(@"#name#", employee.Name).Replace(@"#bankAccountId#", employee.BankAccountId.ToString()).Replace(@"#positionId#", employee.PositionId.ToString()).Replace(@"#role#", employee.Role.ToString()).Replace(@"#e_login#"
                , employee.Login).Replace(@"#e_password#", employee.Password),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                response.Close();
                
                return true;
            }
            return false;
        }

        public bool EditEmployee(Employee oldEmployee, Employee newEmployee)
        {
            HttpWebResponse response = Client.GetResponse(EDIT_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password).Replace(@"#name#", newEmployee.Name).Replace(@"#bankAccountId#", newEmployee.BankAccountId.ToString()).Replace(@"#positionId#", newEmployee.PositionId.ToString()).Replace(@"#role#", newEmployee.Role.ToString()).Replace(@"#e_login#"
                , newEmployee.Login).Replace(@"#e_password#", newEmployee.Password).Replace(@"#id#", oldEmployee.Id.ToString()),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                response.Close();
                
                return true;
            }
            return false;
        }

        public bool DeleteEmployee(Employee employee)
        {
            HttpWebResponse response = Client.GetResponse(DEL_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password).Replace(@"#id#", employee.Id.ToString()),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                response.Close();

                return true;
            }
            return false;
        }

        public IEnumerable<Employee> GetAll()
        {
            HttpWebResponse response = Client.GetResponse(GET_ALL_REQ.Replace(@"#login#", Login).Replace(@"#password#", Password),
                                                          "POST",
                                                          Defaults.DEFAULT_CONTENTTYPE,
                                                          null);

            if (response != null)
            {
                StreamReader responseReader = new StreamReader(response.GetResponseStream());
                string       jsonResult     = responseReader.ReadToEnd();

                response.Close();
                return ParseJson(jsonResult);
            }
            return null;
        }
    }
}
